package com.miaomiao.service.system.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.extra.mail.MailUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.miaomiao.common.RedisPrefix;
import com.miaomiao.common.Result;
import com.miaomiao.domain.system.RegisterBody;
import com.miaomiao.domain.system.User;
import com.miaomiao.exception.ServiceException;
import com.miaomiao.service.system.ResetService;
import com.miaomiao.service.system.UserService;
import com.miaomiao.utils.RedisCache;
import com.miaomiao.utils.RsaUtils;
import com.miaomiao.utils.SecurityUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
public class ResetServiceImpl implements ResetService {

    @Autowired
    private TemplateEngine templateEngine;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private UserService userService;

    @Override
    public Result senCode(String email) {
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200,100,6,20);
        String code = lineCaptcha.getCode();
        String uuid = IdUtil.simpleUUID();
        String key = RedisPrefix.RESET_CODE_PRE + uuid;
        DateTime expireTime = DateUtil.offsetMinute(new Date(), 5);

        // 设置渲染到html页面对应的值
        Context context = new Context();
        context.setVariable("SYSTEM_NAME","家具快计管理系统");
        context.setVariable("CODE",code);
        context.setVariable("SYSTEM_URL","http://139.186.109.251/xxjszs");
        context.setVariable("EXPIRE_TIME",expireTime.toString());
        //利用模板引擎加载html文件进行渲染并生成对应的字符串
        String emailContent = templateEngine.process("emailTemplate_resetPassword", context);

        MailUtil.send(email,"家具快记管理系统重置密码邮件",emailContent,true);
        redisCache.setCacheObject(key,code,5, TimeUnit.MINUTES);
        Map<String, String> map = new HashMap<>();
        map.put("uuid",uuid);
        return Result.success(map);
    }

    @Override
    public Result resetPassword(RegisterBody registerBody) {
        try{
            registerBody.setPassword(RsaUtils.decryptByPrivateKey(registerBody.getPassword()));
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("密码解析错误!");
        }
        User user = null;
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        if(Objects.isNull(SecurityUtils.getLoginUser().getUser())){
            queryWrapper.eq(User::getUserName,registerBody.getUsername());
             user = userService.getOne(queryWrapper);
        }else{
             user = SecurityUtils.getLoginUser().getUser();
        }

        if(Objects.isNull(user) || Strings.isEmpty(registerBody.getEmail()) || !registerBody.getEmail().equals(user.getEmail())){
            return Result.error("邮箱与该用户注册时的邮箱不一致!");
        }else{
            validateCaptcha(registerBody.getCode(),registerBody.getUuid());
            queryWrapper.clear();
            user.setPassword(SecurityUtils.encryptPassword(registerBody.getPassword()));
            queryWrapper.eq(User::getUserId,user.getUserId());
            boolean update = userService.update(user, queryWrapper);
            if(update){
                return Result.success("重置密码成功");
            }else{
                return Result.error("重置密码失败");
            }
        }
    }

    /**
     * 校验验证码
     *
     * @param code 验证码
     * @param uuid 唯一标识
     * @return 结果
     */
    public void validateCaptcha(String code, String uuid) {
        String verifikey = RedisPrefix.RESET_CODE_PRE + uuid;
        String verifyCode = redisCache.getCacheObject(verifikey);
        if(verifyCode == null){
            throw new RuntimeException("验证码已失效");
        }
        if(!code.toLowerCase().equals(verifyCode.toLowerCase())){
            throw new RuntimeException("验证码错误");
        }else{
            redisCache.deleteObject(verifikey);
        }
    }
}
